package net.cyue.android;

import android.app.Activity;
import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.MediaStore;

import com.kongzue.dialogx.dialogs.PopTip;
import com.kongzue.dialogx.dialogs.TipDialog;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Base64;
import java.util.UUID;

import okhttp3.Callback;
import okhttp3.Headers;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;


public class Util
{
    public static final String UUID_PATH = Environment.getExternalStorageDirectory().getPath() + "/.cyue-share";
    public static final int REQUEST_IMAGE_GET = 1;
    private static UtilCallback<Uri> albumCallback;

    private static final OkHttpClient httpClient = new OkHttpClient.Builder().build();


    public static String createUUID() {
        return UUID.randomUUID().toString();
    }

    public static String getUniqueID()
    {
        String path = Util.UUID_PATH;
        File dir = new File(path);
        if (!dir.exists())
        {
            dir.mkdirs();
            if (!dir.exists())
            {
                return null;
            }
        }

        String filePath = dir.getAbsolutePath() + "/uuid";
        File file = new File(filePath);
        if (!file.exists())
        {
            String uuid = Util.createUUID();
            try {
                OutputStream out = new FileOutputStream(file);
                out.write(uuid.getBytes());
            } catch (IOException e) {
                return null;
            }
            return uuid;
        }

        try {
            InputStream in = new FileInputStream(file);
            byte[] bs = new byte[in.available()];
            in.read(bs);
            return new String(bs);
        } catch (IOException e) {
            return null;
        }
    }


    public static boolean deleteFileOrDirectory(File dir)
    {
        if (!dir.exists()) {
            PopTip.show("要删除的文件或文件夹不存在");
            return false;
        } else if (dir.isFile()) {
            return dir.delete();
        }

        File[] files = dir.listFiles();
        // 空文件夹
        if (files == null || files.length == 0)
        {
            return dir.delete();
        }
        for (File f : files)
        {
            if (f.isDirectory())
            {
                Util.deleteFileOrDirectory(f);
                continue;
            }
            f.delete();
        }
        return true;
    }


    public static void write2File(InputStream input, String savePath)
            throws IOException
    {
        int length;
        byte[] bs = new byte[2048];
        OutputStream output = new FileOutputStream(savePath);
        while ((length = input.read(bs)) != -1)
        {
            output.write(bs, 0 ,length);
        }
        output.flush();
        output.close();
    }


    public static void copyFileOrDirectory(String filePath, String savePath)
            throws IOException
    {
        File fIn = new File(filePath);
        File fOut = new File(savePath);
        if (!fIn.exists())
            return;
        if (fIn.isFile())
        {
            Util.write2File(new FileInputStream(filePath), savePath);
            return;
        }
        if (fIn.isDirectory()) {
            fOut.mkdirs();
            String basePath = fOut.getAbsolutePath();
            File[] files = fIn.listFiles();
            for(File f : files)
            {
                String p = basePath + "/" + f.getName();
                if (f.isFile()) {
                    Util.write2File(new FileInputStream(f), p);
                } else if (f.isDirectory()) {
                    Util.copyFileOrDirectory(f.getAbsolutePath(), p);
                }
            }
        }
    }


    public static void moveFileOrDirectory(String filePath, String savePath)
            throws IOException
    {
        File f = new File(filePath);
        Util.copyFileOrDirectory(filePath, savePath);
        Util.deleteFileOrDirectory(f);
        if (f.exists())
        {
            f.delete();
            f.deleteOnExit();
        }
    }


    public static void downloadFile
        (
            Activity activity,
            String url,
            String name,
            UtilCallback<File> finishedCallback
        )
    {
        String filePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() + "/" + name;
        File file = new File(filePath);
        if (file.exists())
            file.delete();

        DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url))
                .setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, name)
                .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);

        DownloadManager downloadManager = (DownloadManager) activity.getSystemService(Context.DOWNLOAD_SERVICE);
        long downloadID = downloadManager.enqueue(request);

        IntentFilter filter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
        BroadcastReceiver receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                long completeDownloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
                if (completeDownloadId == downloadID)
                {
                    finishedCallback.f(new File(filePath));
                }
            }
        };

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
        {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
            {
                activity.registerReceiver(
                        receiver,
                        filter,
                        Context.RECEIVER_EXPORTED
                );
            } else {
                activity.registerReceiver(receiver, filter);
            }
        }

    }


    public static String readFileToBaseString(InputStream input)
            throws IOException
    {
        byte[] bs = new byte[input.available()];
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            input.read(bs);
            input.close();
            return Base64.getEncoder().encodeToString(bs);
        }

        TipDialog.show("安卓版本过低");
        return null;
    }
    public static String readFileToBaseString(String path)
            throws IOException
    {
        File file = new File(path);
        if (!file.exists())
            return null;
        FileInputStream input = new FileInputStream(file);
        return Util.readFileToBaseString(input);
    }



    public static String getImageFilePathFromContentUri
        (
            Uri uri,
            ContentResolver contentResolver
        )
    {
        String filePath;
        String[] filePathColumn = {MediaStore.MediaColumns.DATA};

        Cursor cursor = contentResolver.query(uri, filePathColumn, null, null, null);
//      也可用下面的方法拿到cursor
//      Cursor cursor = this.context.managedQuery(selectedVideoUri, filePathColumn, null, null, null);

        cursor.moveToFirst();

        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
        filePath = cursor.getString(columnIndex);
        cursor.close();
        return filePath;
    }


    public static void openAlbum(Activity activity, UtilCallback<Uri> callback)
    {
        Util.albumCallback = callback;
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.setType("image/*");
        if (intent.resolveActivity(activity.getPackageManager()) != null) {
            activity.startActivityForResult(intent, Util.REQUEST_IMAGE_GET);
        }
    }


    public static void callAlbumCallback(Uri picturePath)
    {
        Util.albumCallback.f(picturePath);
    }


    public static void toBrowser(Activity activity, String url)
    {
        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
        activity.startActivity(intent);
    }



    public static void httpRequest(
            String method,
            String url,
            Headers headers,
            RequestBody requestBody,
            Callback callback
        )
    {
        Request.Builder builder = new Request.Builder()
                .url(url)
                .method(method, requestBody);

        if (headers != null)
            builder.headers(headers);

        Request request = builder.build();
        Util.httpClient.newCall(request).enqueue(callback);
//        Call call = Util.httpClient.newCall(request);
//        try {
//            Response response = call.execute();
//            callback.onResponse(call, response);
//        } catch (IOException e) {
//            callback.onFailure(call, e);
//        }
    }


    public static void httpGet(
            String url,
            Headers headers,
            RequestBody requestBody,
            Callback callback
        )
            throws IOException
    {
        Util.httpRequest(
            "GET",
            url,
            headers,
            requestBody,
            callback
        );
    }


    public static void httpPost(
            String url,
            Headers headers,
            RequestBody requestBody,
            Callback callback
            )
            throws IOException
    {
        Util.httpRequest(
            "POST",
            url,
            headers,
            requestBody,
            callback
        );
    }


    public static void httpPut(String url, Headers headers, RequestBody requestBody, Callback callback)
            throws IOException
    {
        Util.httpRequest(
            "PUT",
            url,
            headers,
            requestBody,
            callback
        );
    }


    public static void httpDelete(String url, Headers headers, RequestBody requestBody, Callback callback)
            throws IOException
    {
        Util.httpRequest(
            "DELETE",
            url,
            headers,
            requestBody,
            callback
        );
    }
}


